import mongoose, { Schema } from 'mongoose';
import channelHandler from '../handler/channelHandlers';
import { getUserBaseInfo } from '../common/roles';

const schema = new Schema(
  {
    username: { type: String },
    nickname: { type: String },
    mobile: { type: String },
    jiuquId: { type: String, index: true },
    headImgUrl: { type: String },
    token: {
      access_token: String,
      expires_in: Number,
      refresh_token: String,
      token_type: String,
    },
    isRobot: { type: Boolean, default: false },
    group: { type: Schema.Types.ObjectId, ref: 'Group' },
    channels: [{ type: Schema.Types.ObjectId, ref: 'Channel' }],
    createdAt: { type: Date, default: Date.now },
    userSocialIds: [{ type: String }],
    service: {
      role: String,
      group: Number,
      groupName: String,
      id: Number,
    },
  },
  {
    collection: 'users',
  },
);

schema.methods.getBasicInfo = function getBasicInfo() {
  return {
    id: this.id,
    username: this.username,
    nickname: this.nickname,
    headImgUrl: this.headImgUrl,
    jiuquId: this.jiuquId,
    userSocialIds: this.userSocialIds,
  };
};

schema.methods.getRedisUserNoticeChannelName = function getRedisUserNoticeChannelName() {
  return `user:notice:${this.id}`;
};

schema.methods.isCustomer = function isCustomer() {
  return /Student:.+|Teacher:.+/.test(this.jiuquId);
};

schema.methods.isTeacher = function isTeacher() {
  return /Teacher:.+/.test(this.jiuquId);
};

schema.methods.getTeacherJqId = function getTeacherJqId() {
  return /Teacher:(.+)/.exec(this.jiuquId)[1];
};

schema.methods.getStudentJqId = function getStudentJqId() {
  return /Student:(.+)/.exec(this.jiuquId)[1];
};

schema.methods.isAnonymous = function isAnonymous() {
  return !/^Student:\d+$/.test(this.jiuquId);
};

schema.methods.onTeacherUserNameUpdated = async function onTeacherUserNameUpdated(userInfo) {
  const ChannelModel = mongoose.model('Channel');
  const newTeacherName = userInfo.username;
  const channel = await ChannelModel.findOne({
    isPrivate: true,
    customer: this,
    creator: this,
  });

  channel.name = newTeacherName;
  this.username = newTeacherName;
  this.nickname = newTeacherName;

  return Promise.all([this.save(), channel.save()]);
};

schema.statics.getSystemRobot = async function getSystemRobot() {
  const UserModel = this;
  return UserModel.findOne({ isRobot: true, username: 'System' });
};

schema.statics.findStudentByJiuquId = async function findStudentByJiuquId(jiuquId) {
  const UserModel = this;

  return UserModel.findOne({ jiuquId: `Student:${jiuquId}` });
};

schema.statics.findAnonymousStudent = async function findAnonymousStudent(userSocialId) {
  const UserModel = this;

  return UserModel.findOne({ userSocialIds: userSocialId, jiuquId: `Student:${userSocialId}` });
};

schema.statics.ensureJiuQuUser = async function ensureJiuQuUser(userInfo, role = 'admin') {
  const UserModel = this;
  const GroupModel = mongoose.model('Group');
  const userBaseInfo = getUserBaseInfo(userInfo, role);

  let user = await UserModel.findOne({
    jiuquId: userBaseInfo.jiuquId,
  }).populate('group');

  // 新建用户
  if (!user) {
    user = new UserModel({
      username: userInfo.username,
      headImgUrl: userInfo.headImgUrl || null,
      // findOrCreateCustomerChanel方法使用nickname作为channel名称, 306前端也使用nickname来展示用户名
      nickname: userInfo.nickname || userInfo.username,
      mobile: userInfo.mobile,
      jiuquId: userBaseInfo.jiuquId,
      channels: [],
    });

    await user.save();
  }

  // 关联Group
  if (!user.group) {
    user.group = await GroupModel.findOne({ name: userBaseInfo.userGroupName });
    await user.save();
  }

  // 对于客户账号,确保存在一个channel
  if (user.isCustomer() && user.channels.length === 0) {
    await channelHandler.findOrCreateCustomerChannel(user, {
      group: user.group,
    });
  }

  if (
    (user.username !== userInfo.username || user.nickname !== userInfo.username) &&
    user.isTeacher()
  ) {
    // teacher info update by a307
    await user.onTeacherUserNameUpdated(userInfo);
  }

  return user;
};

export default mongoose.model('User', schema);
